package ia;

import java.util.ArrayList;
import java.util.Collections;

public class Aestrella90 extends Aestrella {
    private ArrayList<Nodo90>  nAbiertos = new ArrayList<Nodo90>();
    private ArrayList<Nodo90>  nCerrados = new ArrayList<Nodo90>();
    private static Aestrella90 instancia = new Aestrella90();
    
    private Aestrella90(){}

    public static Aestrella90 getInstance(){
        return instancia;
    }

    public void propagaMejora(Nodo90 nodo){
        for(Nodo90 n: nodo.getHijos()){
            n.setCoste(nodo.getCoste()+n.getTransicionCoste());
            propagaMejora(n);
        }
    }

    @Override
    public float buscar() {
    	 boolean salir = false;
         float   coste = 0;
     	
         int[] posAbdel  = general.getPosAbdel();
         int[] posGertru = general.getPosGertru();
         int   iteracion = 1;
         int   cont      = 1;
         int[][] matrizPeligrosidades = general.getMatriz();
         
         ArrayList<Nodo90> nSucesores = new ArrayList<Nodo90>();
         ArrayList<Nodo90> recorrido  = new ArrayList<Nodo90>();

         Nodo90 nInicial = new Nodo90(posAbdel[0],posAbdel[1],Orientacion.N);

         nAbiertos.add(nInicial);
         nInicial.setVHeuristica(heuristica.calculaHeuristica(nInicial, posGertru));
         nCerrados.clear();
         
         while(!salir){
             if (nAbiertos.isEmpty()) 
             	          System.out.println("Lista de nodos abiertos vacia");                       

             Nodo90 mejorNodo = Collections.min(nAbiertos);

             System.out.println("Iteración "+iteracion+":");
             System.out.println("Candidatos:              "+ nAbiertos);
             System.out.println("Mejor Nodo:              "+ mejorNodo);
             nAbiertos.remove(mejorNodo);
             
             if(meta(mejorNodo)) {               
                 coste = mejorNodo.getCoste();                
                 System.out.println("\nFin: el nodo encontrado es meta");
                 mejorNodo.mostrarResultado( nCerrados);
                 System.out.println();
                 
                 salir= true;
                 break;
             }
             nCerrados.add(mejorNodo);

             nSucesores = mejorNodo.aplicaOperadores(matrizPeligrosidades);

             for(Nodo90 i:nSucesores){
                 i.setId(cont);
                 cont++;
                 i.setVHeuristica(heuristica.calculaHeuristica(i, posGertru));
             }
             recorrido.addAll(mejorNodo.getAntecesores());
             Collections.reverse(recorrido);
             recorrido.add(mejorNodo);
             System.out.println("Recorrido seguido:       " + recorrido);
             recorrido.clear();
             System.out.println("Descendientes:           " + nSucesores+"\n\n");

             iteracion++;
             ArrayList<Nodo90> aux = new ArrayList<Nodo90>();
             aux.addAll(nSucesores);

             for(Nodo90 s:nSucesores){         
                 s.setPadre(mejorNodo);

                 if(nAbiertos.contains(s)){
                     Nodo90 viejo = nAbiertos.get(nAbiertos.indexOf(s));
                     if(viejo.getCoste()>s.getCoste()) {
                         viejo.setPadre(mejorNodo);
                         s.setId(cont);
                         cont++;
                         viejo.setCoste(s.getCoste());
                         viejo.setVHeuristica(heuristica.calculaHeuristica(viejo, posGertru));
                     }
                     aux.remove(s);
                     aux.add(viejo);
                 }
                 if( nCerrados.contains(s)){
                     Nodo90 viejo =  nCerrados.get( nCerrados.indexOf(s));                    
                     if(viejo.getCoste()>s.getCoste()){
                         viejo.setPadre(mejorNodo);
                         s.setId(cont);
                         cont++;
                         viejo.setCoste(s.getCoste());
                         viejo.setVHeuristica(heuristica.calculaHeuristica(viejo, posGertru));
                     }
                     aux.remove(s);
                     aux.add(viejo);
                     propagaMejora(viejo);
                 }
                 if(!nAbiertos.contains(s)&! nCerrados.contains(s)){
                     s.setVHeuristica(heuristica.calculaHeuristica(s, posGertru));
                     nAbiertos.add(s);
                     aux.add(s);
                 }
             }
             nSucesores.clear();
             nSucesores.addAll(aux);
             aux.clear();
         }
         
     nAbiertos.clear();
     nCerrados.clear();
     nSucesores.clear();

     return coste;
     }
}